// todo: 去掉与view的关联，与abstractTextEditor关联.

function Commands(textView){
    this.init$Eventable();
    this.$textView = textView;
    // todo: 这个依赖咋办？
    this.$anchorColumn = null;
    this.$byVerticalNav = false;
    this.on(this.$textView.getSelection(), 'Changed', this._onSelectionChanged);
}

Commands.prototype = {
    execCommand: function (cmd, p1, p2, p3){
        switch (cmd) {
        case 'delete':
            return this.doDelete();
        case 'backspace':
            return this.doBackspace();
        case 'indent':
            return this.doIndent();
        case 'outdent':
            return this.doOutdent();
        case 'nav_home':
            return this.doNavHome(p1);
        case 'nav_end':
            return this.doNavEnd(p1);
        case 'nav_page_up':
            return this.doNavPageUp(p1);
        case 'nav_page_down':
            return this.doNavPageDown(p1);
        case 'nav_left':
            return this.doNavLeft(p1);
        case 'nav_right':
            return this.doNavRight(p1);
        case 'nav_up':
            return this.doNavUp(p1);
        case 'nav_down':
            return this.doNavDown(p1);
        case 'selectall':
            return this.doSelectAll();
        case 'copy':
            return this.doCopy();
        case 'cut':
            return this.doCut();
        case 'paste':
            return this.doPaste();
        }
    },
    doDelete: function (){
        var selection = this.$textView.getSelection();
        var textModel = this.$textView.getTextModel();
        if (selection.isCollapsed()) {
            selection.move(_MOVE_RIGHT, selection.getFocusOffset(), true);
        }
        var offset = textModel.setText('', selection.getStartOffset(), selection.getEndOffset());
        selection.setOffset(offset);
        this.$textView.ensureCaretVisible();
    },
    doBackspace: function (){
        var selection = this.$textView.getSelection();
        var textModel = this.$textView.getTextModel();
        if (selection.isCollapsed()) {
            selection.move(_MOVE_LEFT, selection.getFocusOffset(), true);
        }
        var offset = textModel.setText('', selection.getStartOffset(), selection.getEndOffset());
        selection.setOffset(offset);
        this.$textView.ensureCaretVisible();
    },
    doIndent: function (){
        var selection = this.$textView.getSelection();
        var textModel = this.$textView.getTextModel();
        var textLayout = this.$textView.$textLayout;
        if (selection.isCollapsed()) {
            var offset = textModel.setText('\t', selection.getFocusOffset(), selection.getFocusOffset());
            selection.setOffset(offset);
        } else {
            var startOffset = selection.getStartOffset();
            var endOffset = selection.getEndOffset();
            var startLine = textLayout.getRowAndColumn(startOffset)[0];
            var endLine = textLayout.getRowAndColumn(endOffset)[0];
            var focusOffset = selection.getFocusOffset();
            var anchorOffset = selection.getAnchorOffset();
            for (var line=startLine; line<=endLine; line++) {
                if (textModel.getLineLength(line)) {
                    var lineStartOffset = textModel.getLineStartOffset(line);
                    textModel.setText('\t', lineStartOffset, lineStartOffset);
                    if (focusOffset > lineStartOffset) {
                        focusOffset ++;
                    }
                    if (anchorOffset > lineStartOffset) {
                        anchorOffset ++;
                    }
                }
            }
            selection.setFocusOffset(focusOffset);
            selection.setAnchorOffset(anchorOffset);
        }
    },
    doOutdent: function (){
        var selection = this.$textView.getSelection();
        var textModel = this.$textView.getTextModel();
        var textLayout = this.$textView.$textLayout;
        if (selection.isCollapsed()) {
            var r = textLayout.getRowAndColumn(selection.getFocusOffset());
            var column = r[1];
            column = Math.max(0, column % 4 === 0 ? column - 4 : column - column % 4);
            var offset = textLayout.getRowColumnOffset(r[0], column)[0];
            selection.setOffset(offset);
        } else {
            var startOffset = selection.getStartOffset();
            var endOffset = selection.getEndOffset();
            var startLine = textLayout.getRowAndColumn(startOffset)[0];
            var endLine = textLayout.getRowAndColumn(endOffset)[0];
            var focusOffset = selection.getFocusOffset();
            var anchorOffset = selection.getAnchorOffset();
            for (var line=startLine; line<=endLine; line++) {
                if (textModel.getLineLength(line)) {
                    var lineStartOffset = textModel.getLineStartOffset(line);
                    if (textModel.getText(lineStartOffset, lineStartOffset + 1) === '\t') {
                        textModel.setText('', lineStartOffset, lineStartOffset + 1);
                        if (focusOffset > lineStartOffset) {
                            focusOffset --;
                        }
                        if (anchorOffset > lineStartOffset) {
                            anchorOffset --;
                        }
                    }
                }
            }
            selection.setFocusOffset(focusOffset);
            selection.setAnchorOffset(anchorOffset);
        }
    },
    doNavHome: function (shift){
        var selection = this.$textView.getSelection();
        selection.move(_MOVE_HOME, null, shift);
    },
    doNavEnd: function (shift){
        var selection = this.$textView.getSelection();
        var textModel = this.$textView.getTextModel();
        selection.move(_MOVE_END, null, shift);
    },
    doNavPageUp: function (shift){

    },
    doNavPageDown: function (shift){

    },
    doNavLeft: function (shift){
        var selection = this.$textView.getSelection();
        selection.move(_MOVE_LEFT, selection.getFocusOffset(), shift);
        this.$textView.ensureCaretVisible();
    },
    doNavRight: function (shift){
        var selection = this.$textView.getSelection();
        selection.move(_MOVE_RIGHT, selection.getFocusOffset(), shift);
        this.$textView.ensureCaretVisible();
    },
    doNavUp: function (shift){
        var textLayout = this.$textView.getTextLayout();
        var selection = this.$textView.getSelection();
        var targetOffset = selection.getFocusOffset();
        var r = textLayout.getRowAndColumn(targetOffset);
        this.$anchorColumn = this.$anchorColumn != null ? this.$anchorColumn : r[1];
        var row = r[0];
        if (row > 0) {
            targetOffset = textLayout.getRowColumnOffset(row - 1, this.$anchorColumn)[0];
        }
        this.$byVerticalNav = true;
        if (shift) {
            selection.setFocusOffset(targetOffset);
        } else {
            selection.setOffset(targetOffset);
        }
        this.$byVerticalNav = false;
        this.$textView.ensureCaretVisible();
    },
    doNavDown: function (shift){
        var textLayout = this.$textView.getTextLayout();
        var selection = this.$textView.getSelection();
        var targetOffset = selection.getFocusOffset();
        var r = textLayout.getRowAndColumn(targetOffset);
        this.$anchorColumn = this.$anchorColumn != null ? this.$anchorColumn : r[1];
        var row = r[0];
        if (row < textLayout.getRowCount() - 1) {
            targetOffset = textLayout.getRowColumnOffset(row + 1, this.$anchorColumn)[0];
        }
        this.$byVerticalNav = true;
        if (shift) {
            selection.setFocusOffset(targetOffset);
        } else {
            selection.setOffset(targetOffset);
        }
        this.$byVerticalNav = false;
        this.$textView.ensureCaretVisible();
    },
    doSelectAll: function (){
        var selection = this.$textView.getSelection();
        selection.setAnchorOffset(0);
        selection.setFocusOffset(this.$textView.getTextModel().getLength());
        this.$textView.ensureCaretVisible();
    },
    doCopy: function (){
        var sel = this.$textView.$selection;
        var input = this.$textView.$textInput._inputElm();
        var text = this.$textView.$textModel.getText(sel.getStartOffset(), sel.getEndOffset());
        if (text.length < 0x10000) {
            this.$textView.$textInput.setText(text);
        } else {
            input.oncopy = function (evt){
                input.oncopy = null;
                evt = evt || window.event;
                if (window.clipboardData) {
                    window.clipboardData.setData('Text', text);
                    evt.returnValue = false;
                } else if (evt.clipboardData) {
                    evt.clipboardData.setData('text/plain', text);
                    evt.preventDefault();
                }
            };
            setTimeout(function (){
                input.oncopy = null;
            });
        }
        return true;
    },
    doCut: function (){
        var this_ = this;
        var sel = this.$textView.$selection;
        var input = this.$textView.$textInput._inputElm();
        var text = this.$textView.$textModel.getText(sel.getStartOffset(), sel.getEndOffset());
        this_.$textView.$textInput.setText(' ');
        input.oncut = function (evt){
            input.oncut = null;
            evt = evt || window.event;
            if (window.clipboardData) {
                window.clipboardData.setData('Text', text);
                evt.returnValue = false;
            } else if (evt.clipboardData) {
                evt.clipboardData.setData('text/plain', text);
                evt.preventDefault();
            }
            if (!sel.isCollapsed()) {
                this_.doBackspace();
            }
            this_.$textView.$textInput.setText('');
        };
        setTimeout(function (){
            input.oncut = null;
//            this_.$textView.$textInput.sendText();
        });
        return true;
    },
    doPaste: function (){
        var this_ = this;
        var input = this.$textView.$textInput._inputElm();
        input.onpaste = function (evt){
            input.onpaste = null;
            evt = evt || window.event;
            var text;
            if (window.clipboardData) {
                text = window.clipboardData.getData('Text');
                evt.returnValue = false;
            } else if (evt.clipboardData) {
                text = evt.clipboardData.getData('text/plain');
                evt.preventDefault();
            }
            this_.$textView.$textInput.sendText(text);
        };
        setTimeout(function (){
            input.onpaste = null;
//            this_.$textView.$textInput.sendText();
        });
        return true;
    },
    _onSelectionChanged: function (){
        if (!this.$byVerticalNav) {
            this.$anchorColumn = null;
        }
    }
};

Utils.extend(Commands, Eventable);
